package cn.edu.tsinghua.thss.alg.closestpair.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

import cn.edu.tsinghua.thss.alg.closestpair.ClosestPair;
import cn.edu.tsinghua.thss.alg.closestpair.PairResult;
import cn.edu.tsinghua.thss.alg.closestpair.Point;
import cn.edu.tsinghua.thss.alg.closestpair.Rand;

public class ClosestPairFrame extends JFrame implements ActionListener {

	private static final long serialVersionUID = -3919476726078713428L;

	private static ClosestPairFrame frame = new ClosestPairFrame();

	/** The panel that shows the points */
	private PointsPanel pointsPanel;
	/** The status bar */
	private StatusBar statusBar;
	/** Shows the time consumed */
	private JLabel timeLabel;
	/** The field to input the size */
	private JTextField input;
	/** The pair result returned */
	PairResult result;

	public JLabel getTimeLabel() {
		return timeLabel;
	}

	public StatusBar getStatusBar() {
		return statusBar;
	}

	/**
	 * Initialize the frame,loading all panels and components
	 */
	private ClosestPairFrame() {
		pointsPanel = new PointsPanel(this);
		this.setTitle("Closest Pair");
		this.setSize(new Dimension(600, 800));
		this.setLayout(new BorderLayout());
		this.add(pointsPanel, BorderLayout.CENTER);

		JPanel rightPanel = new JPanel();
		rightPanel.setSize(100, 500);
		rightPanel.setLayout(new GridLayout(20, 1));
		JButton button = new JButton("Finish");
		button.setSize(100, 20);
		rightPanel.add(button);
		timeLabel = new JLabel("Time:");
		timeLabel.setSize(100, 20);
		rightPanel.add(timeLabel);

		JLabel randLabel = new JLabel("Random:");
		input = new JTextField("");
		rightPanel.add(randLabel);
		rightPanel.add(input);
		JButton button2 = new JButton("Compute");
		rightPanel.add(button2);
		this.getContentPane().add(rightPanel, BorderLayout.EAST);

		statusBar = new StatusBar();
		this.getContentPane().add(statusBar, BorderLayout.SOUTH);

		button.addActionListener(this);
		button2.addActionListener(this);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
	}

	public static ClosestPairFrame getInstance() {
		return frame;
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().equals("Finish")) {
			Point[] points = pointsPanel.getPoints();
			ClosestPair cp = new ClosestPair();
			long start = System.nanoTime();
			result = cp.findClosestPair(points, points.length);
			long elapsed = System.nanoTime() - start;
			System.out.println(result);
			pointsPanel.drawLine(result.x1, result.y1, result.x2, result.y2);
			timeLabel.setText(elapsed / 1000.0 + "us");
		} else if (e.getActionCommand().equals("Compute")) {
			// Generate random points
			int size = Integer.parseInt(input.getText());
			ClosestPair cp = new ClosestPair();
			Point[] points = Rand.getRandomPoints(size);

			PairResult pr1 = null, pr2 = null;
			long elapsed1 = 0, elapsed2 = 0;

			// Compute the closest pair
			long start = System.currentTimeMillis();
			pr2 = cp.findClosestPair(points, points.length);
			elapsed2 = System.currentTimeMillis() - start;
			System.out.println(pr1 + " " + pr2);
			if (size <= 2000) {
				start = System.currentTimeMillis();
				pr1 = cp.findClosestPairSimple(points, points.length);
				elapsed1 = System.currentTimeMillis() - start;
			}

			// Show the result
			String msg1 = "";
			if (pr1 != null)
				msg1 = "Brute Force:\n" + pr1 + " \nTime:" + elapsed1 + "ms";
			String msg2 = "Divide&Conquer:\n" + pr2 + "\nTime:" + elapsed2
					+ "ms";
			String msg = msg1 + "\n" + msg2;
			JOptionPane.showMessageDialog(this, msg);
		}
	}
}
